<?php
# autoHTML: the dynamic PHP5 library for fast website prototyping
# http://code.google.com/p/autohtml/
#
# Copyright (c) 2010, Shu Zong Chen
# http://freelanceDreams.com/
# All rights reserved. 
# 
# Redistribution and use in source and binary forms, with or without 
# modification, are permitted provided that the following conditions are met: 
# 
#  * Redistributions of source code must retain the above copyright notice, 
#    this list of conditions and the following disclaimer. 
#  * Redistributions in binary form must reproduce the above copyright 
#    notice, this list of conditions and the following disclaimer in the 
#    documentation and/or other materials provided with the distribution. 
#  * Neither the name of autoHTML nor the names of its contributors 
#    may be used to endorse or promote products derived from this software 
#    without specific prior written permission. 
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
# POSSIBILITY OF SUCH DAMAGE.


class wikiParser {
	var $lines = array();
	var $__marked = false;
	var $__markup = "";
	var $__markdown = "";
	var $__header = "";
	
	var $blockmode = array("ul"=>false,
										"ol"=>false,
										"p"=>false);
	function wikiParser($text){
		$lines = explode("\n", $text);
		$this->lines = $lines;
	}
	function __construct($text){
		$this->wikiParser($text);
	}
	function doMarkup(){
		if (!$this->__marked){
			$this->parse();
		}
	}
	function markup(){
		$this->doMarkup();
		return $this->__markup;
	}
	function markdown(){
		$this->doMarkup();
		$return = $this->__markdown;
		if (strlen($return) > 200){
			$a = strpos($return, " ", 200);
			if ($a){
				$return = substr($return, 0, $a) . "...";
			}
		}
		return $return;
	}
	function markshort(){
		$this->doMarkup();
		$return = $this->__markup;
		$return = preg_replace("/<(\/)?p>/", "", $return);
		return $return;
	}

	function parse(){
		//Goes though each line and parses out the block elements
		/*	Available markup
		 * 	=Header1=
		 * 	==Header2==
		 *    * List
		 * 		* of bullets
		 * 		# Numbered
		 * 		# List
		*/
		foreach ($this->lines as $line){
			if (trim($line)==""){
				$this->close_blocks();
				continue;
			}
			if (substr($line, 0, 3)=="  #"){
				$this->open_block("ol");
				$this->__markup .= "\t<li>";
				$this->mark(substr($line, 3));
				$this->__markup .= "</li>\n";
				continue;
			}
			if (substr($line, 0, 3)=="  *"){
				$this->open_block("ul");
				$this->__markup .= "\t<li>";
				$this->mark(substr($line, 3));
				$this->__markup .= "</li>\n";
				continue;
			}
			//The other blocks will behave better with
			//this trimmed
			$line = trim($line);
			
			if (preg_match('/^\-{3,}$/', $line)){
				$this->close_blocks();
				$this->__markup .= "<hr />\n";
				continue;
			}
			if (preg_match('/^(=+)(.+?)(=+)$/', $line, $matches)){
				if ($matches[1]==$matches[3]){
					$l = strlen($matches[1]);
					if ($l == 1 && $this->__header==""){
						$this->__header = $matches[2];
					}else{
						$m = $l;
						$this->__markup .= "<h{$m}>";
						$this->mark($matches[2], false);
						$this->__markup .= "</h{$m}>\n";
					}
				}else{
					$this->mark($line);
				}
				continue;
			}
			
			if ($this->is_block_open()){
				$this->mark("<br />\n");
			}else{
				$this->open_block("p");
			}
			$this->mark($line);
		}
		$this->close_blocks();
		$this->__marked = true;
	}
	function mark($text, $in_markdown = true){
		/*	Available markup:
		 * 	_italic_
		 * 	*bold*
		 * 	'code'
		 * 	{{{code}}}
		 * 	^superscript^
		 * 	,,subscript,,
		 * 	~~strikeout~~	
		*/
		$markup = preg_replace('/(?<!\S)(_)(.+?)(_)/', '<i>$2</i>', $text);
		$markup = preg_replace('/(\*)(.+?)(\*)/', '<b>$2</b>', $markup);
		$markup = preg_replace('/(\*)(.+?)(\*)/', '<b>$2</b>', $markup);
		$markup = preg_replace('@(?<!\[)(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?)@', '<a href="$1">$1</a>', $markup);
		$markup = preg_replace('/(\[)(\S+?) (.+?)(\])/', '<a href="$2">$3</a>', $markup);
		$markup = preg_replace('/([a-zA-Z0-9_.]+?@[a-zA-Z0-9_.]+)/', '<a href="mailto:$1">$1</a>', $markup);
		//$markup = preg_replace('/()(.+?)()/', '', $markup);
		
		$this->__markup .= $markup . ' ';
		if ($in_markdown){
			$this->__markdown .= preg_replace('/<(\/)?.+?>/' , '', $markup) . ' ';
		}
	}
	function is_block_open($block = false){
		if (is_array($block)){
			$arr = $block;
			$check = true;
		}else if ($block){
			$arr = array($block);
			$check = true;
		}else{
			$check = false;
		}
		foreach ($this->blockmode as $key=>$value){
			if ($check){
				if (in_array($key, $arr) && $value == true){
					return true;
				}
			}else{
				if ($value == true){
					return true;
				}
			}
		}
		return false;
	}
	function open_block($block){
		$this->close_blocks($block);
		if ($this->blockmode[$block] === false){
			$this->__markup .= "<{$block}>\n";
			$this->blockmode[$block] = true;
		}
	}
	function close_blocks($ignore=""){
		foreach ($this->blockmode as $mode=>$value){
			if ($mode==$ignore){
				continue;
			}else{
				if ($value){
					$this->__markup .= "</{$mode}>\n";
				}
				$this->blockmode[$mode]=false;
			}
		}
	}
}
?>